package com.netposa.datawarehouse.aggregator.web.model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.netposa.datawarehouse.aggregator.util.ProjectPath;
import com.netposa.library.datawarehouse.aggregate.helper.ResourceDefined.ResourceType;
import com.netposa.library.datawarehouse.aggregate.model.InterfaceInfo;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.collections.MapUtils;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.HTreeMap;
import org.mapdb.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class ModuleTable {
   private static final Logger log = LoggerFactory.getLogger(ModuleTable.class);
   private static final String MODULE_TYPES = "types";
   private final DB mapDb;
   private final ConcurrentMap<String,List<String>> moduleTypes;
   private final ConcurrentMap<String,List<InterfaceInfo>> moduleMap;
   private final ConcurrentMap<String,String> tempMap;

   private ModuleTable(DB mapDb) {
      log.info("current register path: {}", ProjectPath.classPath);
      log.info("current project path: {}", ProjectPath.getRootPath());
      this.moduleTypes = new ConcurrentHashMap<>(4);
      this.moduleMap = new ConcurrentHashMap<>(4);
      this.tempMap = new ConcurrentHashMap(1);
      this.mapDb = mapDb;
   }

   public static ModuleTable getInstance() {
      return SingletonHolder.instance;
   }

   public ConcurrentMap getModuleMap() {
      return this.moduleMap;
   }

   public void putInterfaceInfo(String serviceName, List<InterfaceInfo> interfaceInfos) {
      this.moduleMap.put(serviceName, interfaceInfos);
   }

   public List<InterfaceInfo> getInterfaceInfo(String serviceName) {
      return this.moduleMap.get(serviceName);
   }

   public List getAllInterfaceInfo() {
      List list = new ArrayList();
      this.moduleMap.values().forEach((l) -> {
         list.addAll(l);
      });
      return list;
   }

   public List<String> getModules() {
      Set<String> set = new HashSet<>();
      this.moduleTypes.values().forEach(set::addAll);
      return set.stream().collect(Collectors.toList());
   }

   public List getModules(String typeName) {
      return this.moduleTypes.containsKey(typeName) ? (List)this.moduleTypes.get(typeName) : new ArrayList();
   }

   public List<String> getModuleTypes() {
      return this.moduleTypes.keySet().stream().collect(Collectors.toList());
   }

   public ConcurrentMap init() {
      ConcurrentMap<String,String> typeMap = this.mapDb.hashMap(MODULE_TYPES, Serializer.STRING, Serializer.STRING).createOrOpen();
      Predicate<String> isIn = (i) -> {
         return ResourceType.getList().contains(i);
      };
      typeMap.keySet().stream().filter(isIn).forEach((typeName) -> {
         this.moduleTypes.put(typeName, JSONArray.parseArray(typeMap.get(typeName), String.class));
         this.tempMap.putAll(this.mapDb.hashMap(typeName, Serializer.STRING, Serializer.STRING).createOrOpen());
      });
      if (MapUtils.isNotEmpty(this.tempMap)) {
         this.tempMap.forEach((serviceName, interfaceInfoStr) -> {
            this.putInterfaceInfo(serviceName, JSONArray.parseArray(interfaceInfoStr, InterfaceInfo.class));
         });
      }

      return this.moduleMap;
   }

   public ConcurrentMap stringMap(String typeName, String serviceName, String interfaceInfoStr) {
      this.tempMap.put(serviceName, interfaceInfoStr);
      this.mapDb.hashMap(typeName, Serializer.STRING, Serializer.STRING).createOrOpen().putAll(this.tempMap);
      this.mapDb.commit();
      this.moduleTypes.merge(typeName, Splitter.on(",").splitToList(serviceName), (list, newList) -> {
         return list.containsAll(newList) ? list : ListUtils.union(list, newList);
      });
      this.mapDb.hashMap(MODULE_TYPES, Serializer.STRING, Serializer.STRING).createOrOpen().put(typeName, JSON.toJSONString(this.moduleTypes.getOrDefault(typeName, new ArrayList())));
      this.mapDb.commit();
      return this.tempMap;
   }

   public String getTypeName(String serviceName) {
      String typeName = "";
      Iterator var3 = this.moduleTypes.keySet().iterator();

      String type;
      do {
         if (!var3.hasNext()) {
            return typeName;
         }

         type = (String)var3.next();
      } while(!this.moduleTypes.get(type).contains(serviceName));

      return type;
   }

   public static void main(String[] args) {
      ConcurrentMap<String,String> typeMap = new ConcurrentHashMap<>(2);
      ConcurrentMap asd = new ConcurrentHashMap(2);
      typeMap.put("a", "aaa");
      typeMap.put("b", "bbbb");
      typeMap.put("c", "ccccc");
      System.out.println(typeMap);
      System.out.println(asd);
      System.out.println("------------------------------");
      Predicate<String> isIn = (i) -> {
         return i.equalsIgnoreCase("aaa") || i.equalsIgnoreCase("ccccc");
      };
      asd = typeMap.values().stream().map((v) -> {
         return v.toUpperCase();
      }).distinct().filter(isIn).collect(Collectors.toConcurrentMap((k) -> {
         return k;
      }, (k) -> {
         return k.length();
      }));
      System.out.println(typeMap);
      System.out.println(asd);
      List<String> list = Lists.newArrayList("1", "2", "3", "1");
      Map map = list.stream().collect(Collectors.toMap((key) -> {
         return key;
      }, (value) -> {
         return Lists.newArrayList(value);
      }, (newValueList, oldValueList) -> {
         oldValueList.addAll(newValueList);
         return oldValueList;
      }));
      System.out.println(JSON.toJSONString(map));
      ModuleTable table = getInstance();
   }

   // $FF: synthetic method
/*   ModuleTable(DB x0, Object x1) {
      this(x0);
   }*/

   private static class SingletonHolder {
      public static final ModuleTable instance = new ModuleTable(DBMaker.fileDB("register.db").fileMmapEnable().fileMmapEnableIfSupported().fileMmapPreclearDisable().cleanerHackEnable().transactionEnable().closeOnJvmShutdown().make());
   }
}
